/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "queue.h"
#include "semphr.h"
#include "stm32f1xx_hal_flash.h"
#include "modbus_rtu.h"
#include "ina226.h"
#define GpuSend(...) printf(__VA_ARGS__)  
//#define GpuSend(...) SOFTUART_Printf(__VA_ARGS__) 
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern uint16_t aADCxConvertedData[7];
//extern uint8_t tx_uart1_buff_cmd[31];
//extern uint8_t tx_bms_10_buff[15];
extern uint8_t ac_rx_buff[24];
extern uint8_t ac_rx_cont;
extern uint8_t ac_rx_status;
extern uint8_t aa;
u8 Status_BUS;
u8 BAT_EN = 1;
uint16_t temp_v;
uint16_t temp_i;
uint16_t temp_ii;
uint16_t battery_cyc = 0;
u8 IB1_STATE;
u8 IB2_STATE;
u8 POWER_STATE = 0 ;
u8 PREV_POWER_STATE = 0;  // 上一次电源状态，用于检测电源恢复
uint8_t bms_state = 0;
uint8_t ch_stade = 1;
uint8_t ch_stade1 = 0;
uint8_t battery_full = 0;  // 电池充满标志位
uint8_t bat_stade1 = 1;
uint8_t rx_usart1_cnt;
uint8_t ModebusTxBuff[200];
//uint8_t udp_txbuff[200];
uint8_t ModebusRxBuff[128];
uint16_t rtu_buff[1090]={0};
uint8_t rx_usart3_cnt;
uint8_t ModebusTxBuff_M[128];
uint8_t ModebusRxBuff_M[128];
u8 bat_charge_indicator = 0;
u8 bat_discharge_indication = 0;
uint8_t proto = 0;
uint8_t rtu = 0;
MODEBUS_HANDLE ModebusHandle1;
MRTU_SLAVE_INFO FrameInfo1;	//modebus????

MODEBUS_HANDLE ModebusHandle2;
MRTU_SLAVE_INFO FrameInfo2;	//modebus????

uint16_t modbue_SlaveAddr = 1;
uint16_t udp_status =0;
float battery_capacity = 0;
float battery_capacity_rate = 5000;
extern xQueueHandle xQueueRx_pc_uart1;
extern xQueueHandle xQueueRx_bms_uart2;
extern xQueueHandle xQueueRx_ac_uart3;

xSemaphoreHandle xSemaphoreRecf_pc_uart1;
xSemaphoreHandle xSemaphoreRecf_bms_uart2;
xSemaphoreHandle xSemaphoreRecf_ac_uart3;

uint32_t Voltage_Reg,Power_Reg,Voltage_Parameter_Reg,Power_Parameter_Reg,Current_Reg,Current_Parameter_Reg;
int16_t tem;
float ActivePower,ACVotage,ACCurrent;
uint32_t ac_v;
uint16_t ac_w;
uint16_t ac_i;

uint16_t out = 2;

float ac_v_f=0;
float ac_i_f=0;
float ac_w_f=0;

float battery_v = 0;
float battery_i=0;
float battery_i1=0;
float battery_i2=0;
float battery_i3=0;
float battery_c=5000;
float battery_nominal_capacity = 5000; // 电池标称容量(mAh)
float battery_current_capacity = 5000; // 电池当前实际容量(mAh)
int SOC=0;
int SOH=100;

// SOH计算函数，基于容量衰减和循环次数
int CalculateSOH(void) {
    float capacity_factor = 0.0f;
    float cycle_factor = 0.0f;
    int calculated_SOH = 100;
    
    // 基于容量衰减的计算 (占80%权重)
    if (battery_nominal_capacity > 0) {
        capacity_factor = (battery_current_capacity / battery_nominal_capacity) * 80.0f;
    }
    
    // 基于循环次数的计算 (占20%权重)
    // 假设500次循环后SOH降至80%，线性衰减
    if (battery_cyc <= 500) {
        cycle_factor = 20.0f - (battery_cyc * 0.04f); // 每循环减少0.04%
    } else {
        cycle_factor = 0.0f; // 超过500次循环，循环因子为0
    }
    
    // 计算总SOH
    calculated_SOH = (int)(capacity_factor + cycle_factor);
    
    // 限制SOH范围在0-100之间
    if (calculated_SOH > 100) calculated_SOH = 100;
    if (calculated_SOH < 0) calculated_SOH = 0;
    
    return calculated_SOH;
}

// 更新电池当前容量的函数 (可根据实际充放电数据更新)
void UpdateBatteryCapacity(void) {
    // 这里可以根据实际充放电数据和库仑计数来更新容量
    // 目前使用一个简化的模型，基于循环次数估算容量衰减
    
    // 假设每100次循环容量衰减3%
    float capacity_reduction = 1.0f - (battery_cyc * 0.03f / 100.0f);
    if (capacity_reduction < 0.6f) capacity_reduction = 0.6f; // 最低保留60%容量
    
    battery_current_capacity = battery_nominal_capacity * capacity_reduction;
}
float device_tem= 37.8;
u8 bat_state = 0;
u8 ctrl_1 = 1; //������ؿ�����

uint8_t BAT_STATE1 = 1;
uint8_t out_lcd = 1;
uint16_t udp_rtu_con=0;
uint16_t modbue_Baud = 1152;
uint16_t bat_under_charge = 5;
uint16_t OUT1_266 = 0;
uint16_t OUT2_266 = 0;
uint16_t BAT_266 = 1;
uint16_t out_sum = 2;
uint16_t pcb_sum = 1;
uint16_t ctrl_2 = 0xffff;
uint16_t ctrl_3 = 0xffff;
uint16_t ctrl_4 = 0xffff;
uint16_t ctrl_5 = 0xffff;
uint8_t add = 1;
//uint16_t out = 3;
uint8_t m_s = 1;

float tempre =0;

int num_pic_battery =5;

int num_pic_bat_status =2;
uint16_t temp_v1[100]={0};
uint16_t temp_v2[100]={0};
uint16_t temp_v3[100]={0};
uint16_t temp_v4[100]={0};
uint16_t temp_v5[100]={0};
uint16_t temp_v6[100]={0};
uint16_t temp_v7[100]={0};

uint16_t temp_i1[100]={0};
uint16_t temp_i2[100]={0};
uint16_t temp_i3[100]={0};
uint16_t temp_i4[100]={0};
uint16_t temp_i5[100]={0};
uint16_t temp_i6[100]={0};
uint16_t temp_i7[100]={0};

float dc_v[13]={0};
float dc_i[13]={0};

uint8_t calibration_i;

uint8_t bms_add;

extern uint8_t adc_cont;

float v_k[13] ={1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
float i_k[13]={2.5,2.5,1.22,1.25,1.25,1.25,2.5,2.5,1.22,1.25,1.25,1.25,1.25};
float i_k_a[13]={1,1,1,1,1,1,1,1,1,1,1,1,1};

uint16_t t_adc[341]={123,131,139 ,148 ,157 ,167 ,178 ,189 ,200 ,212 ,225 ,239 ,253, 268 ,284 ,300 
,316 ,334 ,352 ,371 ,391 ,411 ,432 ,455 ,478 ,501 ,526 ,551 ,577 ,604 ,632 ,661 ,691 ,722 ,754 ,786 ,820 ,855 
,890 ,926 ,964 ,1000 ,1038 ,1077 ,1116 ,1156 ,1197 ,1238 ,1281 ,1323 ,1367 ,1410 ,1455 ,1499 ,1544 ,1590 ,1635 
,1681 ,1727 ,1773 ,1819 ,1865 ,1911 ,1957 ,2003 ,2048 ,2093 ,2138 ,2183 ,2227 ,2271 ,2314 ,2357 ,2399 ,2441 ,2482 
,2523 ,2562 ,2602 ,2640 ,2678 ,2716 ,2752 ,2788 ,2823 ,2857 ,2891 ,2924 ,2956 ,2988 ,3019 ,3049 ,3078 ,3106 ,3134 ,3161 ,3188 
,3214 ,3239 ,3263 ,3287 ,3310 ,3333 ,3355 ,3376 ,3397 ,3417 ,3437 ,3456 ,3474 ,3492 ,3510 ,3527 ,3543 ,3559 ,3575 ,3590 
,3604 ,3619 ,3632 ,3646 ,3659 ,3671 ,3684 ,3696 ,3707 ,3718 ,3729 ,3740 ,3750 ,3760 ,3770 ,3779 ,3788 ,3797 ,3806 ,3814 ,3822 
,3830 ,3837 ,3844 ,3851 ,3858 ,3865 ,3871 ,3877 ,3883 ,3889 ,3894 ,3900 ,3905 ,3910 ,3915 ,3920 ,3925 ,3929 ,3934 ,3938 ,3942 
,3946 ,3950 ,3954 ,3957 ,3961 ,3964 ,3968 ,3971 ,3974 ,3978 ,3981 ,3984 ,3987 ,3990 ,3993 ,3995 ,3998 ,4001 ,4003 ,4005 ,4008 
,4010 ,4012 ,4014 ,4016 ,4018 ,4020 ,4022 ,4024 ,4026 ,4027 ,4029 ,4031 ,4032 ,4034 ,4035 ,4036 ,4038 ,4039 ,4040 ,4042 ,4043 
,4044 ,4045 ,4046 ,4047 ,4048 ,4050 ,4051 ,4052 ,4052 ,4053 ,4054 ,4055 ,4056 ,4057 ,4058 ,4059 ,4059 ,4060 ,4061 ,4062 ,4063 
,4063 ,4064 ,4065 ,4065 ,4066 ,4067 ,4067 ,4068 ,4068 ,4069 ,4070 ,4070 ,4071 ,4071 ,4072 ,4072 ,4073 ,4073 ,4074 ,4074 ,4074 
,4075 ,4075 ,4076 ,4076 ,4076 ,4077 ,4077 ,4077 ,4078 ,4078 ,4078 ,4079 ,4079 ,4079 ,4080 ,4080 ,4080 ,4080 ,4081 ,4081 ,4081 
,4081 ,4082 ,4082 ,4082 ,4082 ,4083 ,4083 ,4083 ,4083 ,4084 ,4084 ,4084 ,4084 ,4085 ,4085 ,4085 ,4085 ,4085 ,4086 ,4086 ,4086 
,4086 ,4086 ,4086 ,4087 ,4087 ,4087 ,4087 ,4087 ,4087 ,4087 ,4088 ,4088 ,4088 ,4088 ,4088 ,4088 ,4088 ,4089 ,4089 ,4089 ,4089 
,4089 ,4089 ,4089 ,4089 ,4089 ,4089 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4090 ,4091 ,4091 ,4091 ,4091 
,4091 ,4091 ,4091 ,4091 ,4091 ,4091 ,4091 ,4091 ,4091 ,4092 ,4092 ,4092 ,4092 ,4092 
};

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */


uint32_t writeFlashData = 0x55555555;
uint32_t addr = 0x08010000; //// c8t6

/* �豸ʵ�� */
INA226_Dev dev1 = {
    .scl_port = I2C_SCL_GPIO_Port,
    .scl_pin = I2C_SCL_Pin,
    .sda_port = I2C_SDA_GPIO_Port,
    .sda_pin = I2C_SDA_Pin,
    .shunt_r = 0.01f,    // 20m��
    .max_current = 3.2768f,  // 4A
    .addr = 0x40
};

INA226_Dev dev2 = {
    .scl_port = I2C_SCL_GPIO_Port,
    .scl_pin = I2C_SCL_Pin,
    .sda_port = I2C_SDA_GPIO_Port,
    .sda_pin = I2C_SDA_Pin,
    .shunt_r = 0.01f,    // 20m��
    .max_current = 3.2768f,   // 4A
    .addr = 0x41
};
INA226_Dev dev3 = {
    .scl_port = I2C_SCL_GPIO_Port,
    .scl_pin = I2C_SCL_Pin,
    .sda_port = I2C_SDA_GPIO_Port,
    .sda_pin = I2C_SDA_Pin,
    .shunt_r = 0.01f,    // 20m��
    .max_current = 3.2768f,  // 4A
    .addr = 0x44
};

//FLASH写入数据测试
void writeFlashTest(void)
{
	//1、解锁FLASH
  HAL_FLASH_Unlock();
	
	//2、擦除FLASH
	//初始化FLASH_EraseInitTypeDef
	FLASH_EraseInitTypeDef f;
	f.TypeErase = FLASH_TYPEERASE_PAGES;
	f.PageAddress = addr;
	f.NbPages = 1;
	//设置PageError
	uint32_t PageError = 0;
	uint8_t i;
	//调用擦除函数
	HAL_FLASHEx_Erase(&f, &PageError);

	//3、对FLASH烧写
for (i =0;i<=12;i++){
	HAL_FLASH_Program(0x02U, addr+4*i, (uint32_t)(v_k[i]*100));
	}
	for (i =0;i<=12;i++){
	HAL_FLASH_Program(0x02U, addr+4*(i+13), (uint32_t)(i_k[i]*100));
	}
	
	
	HAL_FLASH_Program(0x02U, addr+26*4, (uint32_t)(modbue_SlaveAddr));
	HAL_FLASH_Program(0x02U, addr+27*4, (uint32_t)(udp_status));
	
	for (i =0;i<=12;i++){
	HAL_FLASH_Program(0x02U, addr+4*(i+28), (uint32_t)(i_k_a[i]*100));
	}
	HAL_FLASH_Program(0x02U, addr+41*4, (uint32_t)(modbue_Baud));
	HAL_FLASH_Program(0x02U, addr+42*4, (uint32_t)(SOC));
	HAL_FLASH_Program(0x02U, addr+43*4, (uint32_t)(battery_cyc));
	HAL_FLASH_Program(0x02U, addr+44*4, (uint32_t)(SOH));
	//4¡¢˸סFLASH
	
	
	//4����סFLASH
	
	rtu_buff[151] = modbue_SlaveAddr;
	rtu_buff[154] = udp_status;
	rtu_buff[152] = modbue_Baud;
	rtu_buff[130] = SOC;
	rtu_buff[135] = battery_cyc;
	rtu_buff[131] = SOH;
   HAL_FLASH_Lock();
}

//FLASH读取数据测试
void printFlashTest(void)
{
uint8_t i;
	
	if(((uint16_t) *(__IO uint32_t*)(addr))>=0xffff){
	writeFlashTest();	
	}
	
	for(i=0;i<=12;i++){
	v_k[i] =((float) *(__IO uint32_t*)(addr+4*i)/100.00);
	}

	
	for(i=0;i<=12;i++){
	i_k[i] =((float) *(__IO uint32_t*)(addr+4*(i+13))/100.00);
	}
	modbue_SlaveAddr = ((uint8_t) *(__IO uint32_t*)(addr+26*4));
	udp_status = ((uint16_t) *(__IO uint32_t*)(addr+27*4));	
	
	
	for(i=0;i<=12;i++){
	i_k_a[i] =((float) *(__IO uint32_t*)(addr+4*(i+28))/100.00);
	}
	modbue_Baud = ((uint16_t) *(__IO uint32_t*)(addr+41*4));
	SOC = ((uint16_t) *(__IO uint32_t*)(addr+42*4));	
	battery_cyc = ((uint16_t) *(__IO uint32_t*)(addr+43*4));	
	SOH = ((uint16_t) *(__IO uint32_t*)(addr+44*4));	
	rtu_buff[151] = modbue_SlaveAddr;
	rtu_buff[154] = udp_status;
	rtu_buff[152] = modbue_Baud;
	rtu_buff[130] = SOC;
	rtu_buff[135] = battery_cyc;
	rtu_buff[131] = SOH;
}



/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for myLCD_Task */
osThreadId_t myLCD_TaskHandle;
const osThreadAttr_t myLCD_Task_attributes = {
  .name = "myLCD_Task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow7,
};
/* Definitions for modbus_rtu */
osThreadId_t modbus_rtuHandle;
const osThreadAttr_t modbus_rtu_attributes = {
  .name = "modbus_rtu",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myled_Task */
osThreadId_t myled_TaskHandle;
const osThreadAttr_t myled_Task_attributes = {
  .name = "myled_Task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityLow,
};
/* Definitions for mybms_task */
osThreadId_t mybms_taskHandle;
const osThreadAttr_t mybms_task_attributes = {
  .name = "mybms_task",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityAboveNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */



//////////  adc
osThreadId_t TC_TaskHandle;
const osThreadAttr_t TC_Task_attributes = {
  .name = "TC_Task",
  .priority = (osPriority_t) osPriorityHigh,
  .stack_size = 128 * 4
};
  

void Start_TC_Task(void *argument);

///////////////////////////////////////   pc cmd

osThreadId_t cmd_TaskHandle;
const osThreadAttr_t cmd_Task_attributes = {
  .name = "cmd_Task",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
  

void Start_cmd_Task(void *argument);

///////  bms

osThreadId_t bms_TaskHandle;



/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);
void StartLCD_Task(void *argument);
void Startmodbus_rtu(void *argument);
void Startled_Task(void *argument);
void Startbms_Task(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
	
  /* USER CODE BEGIN Init */
       
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
	

  /* creation of myLCD_Task */
  myLCD_TaskHandle = osThreadNew(StartLCD_Task, NULL, &myLCD_Task_attributes);
	

  /* creation of modbus_rtu */
  modbus_rtuHandle = osThreadNew(Startmodbus_rtu, NULL, &modbus_rtu_attributes);
	

  /* creation of myled_Task */
  myled_TaskHandle = osThreadNew(Startled_Task, NULL, &myled_Task_attributes);
	

  /* creation of mybms_task */
  mybms_taskHandle = osThreadNew(Startbms_Task, NULL, &mybms_task_attributes);
	

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	
	
  TC_TaskHandle= osThreadNew(Start_TC_Task, NULL, &TC_Task_attributes);
	
	
  cmd_TaskHandle= osThreadNew(Start_cmd_Task, NULL, &cmd_Task_attributes);
	
	
	//bms_TaskHandle= osThreadNew(Start_bms_Task, NULL, &bms_Task_attributes);
	 
//	ac_TaskHandle= osThreadNew(Start_ac_Task, NULL, &ac_Task_attributes);
		
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	
	uint8_t temp;
	
	
	
	 MODEBUS_slave_Init(&ModebusHandle1, 01, modbue_Baud*100, ModebusRxBuff, ModebusTxBuff, 128-1, 200);
	
	 LL_TIM_ClearFlag_UPDATE(TIM1);
	 //LL_TIM_ClearFlag_UPDATE(TIM3);
	
	 LL_TIM_EnableIT_UPDATE(TIM1);
   
	
	
	
	 // LL_TIM_EnableIT_UPDATE(TIM3);
   LL_TIM_EnableCounter(TIM3);
	
	
  LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,3);
	
  LL_DMA_SetPeriphAddress(DMA1,LL_DMA_CHANNEL_1,LL_ADC_DMA_GetRegAddr(ADC1,LL_ADC_DMA_REG_REGULAR_DATA));
 
  LL_DMA_SetMemoryAddress(DMA1,LL_DMA_CHANNEL_1,(uint32_t)aADCxConvertedData);
 
  LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);
	
	LL_DMA_EnableIT_TC(DMA1,LL_DMA_CHANNEL_1);
	
	
	
	LL_ADC_Enable(ADC1);
	 
	LL_ADC_StartCalibration(ADC1);
 
  while( LL_ADC_IsCalibrationOnGoing(ADC1));
	
  LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
 
  
      temp =((uint8_t) *(__IO uint32_t*)(addr));

	if(temp == 0xff){
	
	writeFlashTest();
	}
	else{
	printFlashTest();}
	
	osDelay(2000);	
  /* Infinite loop */
  for(;;)
  {	
		
		LL_GPIO_ResetOutputPin(RUN_LED_GPIO_Port,RUN_LED_Pin);
		osDelay(500);
		LL_GPIO_SetOutputPin(RUN_LED_GPIO_Port,RUN_LED_Pin);
	 // printf("test for task ");
		osDelay(500);
		
		 
  }
  /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartLCD_Task */
/**
* @brief Function implementing the myLCD_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartLCD_Task */
void StartLCD_Task(void *argument)
{
  /* USER CODE BEGIN StartLCD_Task */
  /* Infinite loop */
  /*LCD��ʾ*/	

	/*uint8_t a; 
	osDelay(1000);
	GpuSend("SPG(16);");
  GpuSend("\r\n");
  osDelay(1000);*/
  for(;;)
  {
/*
GpuSend("SPG(16);");
GpuSend("\r\n");
osDelay(50);
		
if(rtu_buff[136]&0X0001)	{
GpuSend("LABL(16,160,55,260,'����������',3,1);");
	if (ac_v >50*100){
			 rtu_buff[139] = ac_v ;	
			 rtu_buff[140] = ac_i ;				  
		   ac_v_f = ac_v/100.00;	
			 ac_i_f = (float) (ac_i /100.00);
			// rtu_buff[197] = ac_w ; 
       ac_w_f = (float)	ac_w;		  
			
		  }
	}
	else{
	GpuSend("LABL(16,160,55,260,'��ع�����',3,1);");
	ac_v_f = 0;
	ac_i_f = 0;
	ac_w_f = 0;
	rtu_buff[139] = 0 ;	
  rtu_buff[140] = 0 ;
//  rtu_buff[197] = 0 ; 		
	}
	
	if(BAT_EN == 0){
			GpuSend("LABL(16,262,55,310,'������',3,0);");
		}
	else{GpuSend("LABL(16,262,55,310,'������',3,0);");}
		
//	GpuSend("\r\n");
//	osDelay(200);
GpuSend("LABL(16,90,85,150,'127/12B',3,0);");
GpuSend("LABL(16,75,110,150,'%dV/%.1fA',3,0);",(uint16_t)(ac_v_f),ac_i_f);
GpuSend("LABL(16,235,85,314,'%.1fV%.1fA',3,0);",dc_v[0],dc_i[0]);	
GpuSend("LABL(16,235,110,314,'%.1fV%.1fA',3,0);",dc_v[1],dc_i[1]);
//GpuSend("\r\n");
//osDelay(200);	
GpuSend("LABL(16,90,185,160,'%.1fV',2,0);",battery_v);
GpuSend("LABL(16,250,185,310,'%.2fA',2,0);",battery_i);
GpuSend("LABL(16,250,205,310,'%.1f��',2,0);",device_tem);
GpuSend("LABL(16,90,205,115,'%d',2,0);",battery_capacity);
//GpuSend("\r\n");
//osDelay(200);
		if(num_pic_bat_status == 3)
		{
		GpuSend("LABL(16,120,155,218,'�����',2,0);");
		}
		if(num_pic_bat_status == 2)
		{
		GpuSend("LABL(16,120,155,218,'�ŵ���',2,0);");
		}
		if(num_pic_bat_status == 4)
		{
		GpuSend("LABL(16,120,155,218,'������',2,0);");
		}		
		GpuSend("PIC(218,155,%d);",num_pic_battery);
		GpuSend("\r\n");
		osDelay(1000);
	  
 
 if(rtu_buff[136]&0X0001)	{
GpuSend("LABL(16,160,55,260,'����������',3,1);");
	if (ac_v >50*100){
			 rtu_buff[195] = ac_v ;	
			 rtu_buff[196] = ac_i ;				  
		   ac_v_f = ac_v/100.00;	
			 ac_i_f = (float) (ac_i /100.00);
			 rtu_buff[197] = ac_w ; 
       ac_w_f = (float)	ac_w;		  
			
		  }
	}
	else{
	GpuSend("LABL(16,160,55,260,'��ع�����',3,1);");
	ac_v_f = 0;
	ac_i_f = 0;
	ac_w_f = 0;
	rtu_buff[195] = 0 ;	
  rtu_buff[196] = 0 ;
  rtu_buff[197] = 0 ; 		
	}
 
if(rtu_buff[136]&0X0001)	{
GpuSend("SET_TXT(0,����������);");}
else{
GpuSend("SET_TXT(0,��ع�����);");}
if(BAT_EN == 0){
GpuSend("SET_TXT(13,���������);");
}
else{GpuSend("SET_TXT(13,��ض�����);");}
//GpuSend("\r\n");
//osDelay(1000);
if(num_pic_bat_status == 3){
GpuSend("SET_TXT(6,��س����);");}
if(num_pic_bat_status == 2){
GpuSend("SET_TXT(6,��طŵ���);");}
if(num_pic_bat_status == 4){
GpuSend("SET_TXT(6,��ش�����);");}
GpuSend("SET_TXT(5,%.1f��);",device_tem);
GpuSend("SET_TXT(12,%.1f��);",device_tem);
//GpuSend("\r\n");
//osDelay(1000);
GpuSend("SET_TXT(11,%d%%);",battery_capacity);
GpuSend("SET_TXT(10,%.1fA);",battery_i);
GpuSend("SET_TXT(9,%.1fV);",battery_v);
GpuSend("SET_TXT(3,%.1fV%.1fA);",dc_v[0],dc_i[0]);
GpuSend("SET_TXT(4,%.1fV%.1fA);",dc_v[1],dc_i[1]);
GpuSend("SET_TXT(2,%dV/%.1fA);",(uint16_t)(ac_v_f),ac_i_f);
GpuSend("SET_PROG(7,%d);",battery_capacity);
GpuSend("\r\n");*/
osDelay(1000);
	}

  /* USER CODE END StartLCD_Task */
}

/* USER CODE BEGIN Header_Startmodbus_rtu */
/**
* @brief Function implementing the modbus_rtu thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Startmodbus_rtu */
void Startmodbus_rtu(void *argument)
{
  /* USER CODE BEGIN Startmodbus_rtu */
  /* Infinite loop */
	/*MODEBUS_RTU��Ӧ*/
	
u16 data;
	u16 RegBuff[128];
	u8 i;
	u32 cnt1 = 0,cnt2 = 0;
	u8 Fun;

	for(i = 0;i < 10;i ++)
	{
		RegBuff[i] = i+1;
	}
	
	for(;;)
	{
		if(rtu){
		rtu = 0;
		cnt2 = cnt1;
	//	cnt1 = MODEBUS_GetDataCnt(ModebusHandle1.UartCh);
		
		cnt1 = rx_usart1_cnt;
		rx_usart1_cnt = 0 ;
	//	if((cnt1 == cnt2) && (cnt1 != 0))
   if( cnt1 != 0)
		{
			LL_USART_DisableIT_RXNE(USART1);
			if(MODEBUS_SLAVE_FramesUnpack(&ModebusHandle1, modbue_SlaveAddr, cnt1, &Fun) == MRTU_OK)
			{
				//usb_printf("????,???:0x%02X\r\n", Fun);
				switch(Fun)
				{
					case MRTU_FUN_READ_HOLD		:				// 3
					case MRTU_FUN_READ_INPUT	:					// 4 
					{
						//??
						MODEBUS_SLAVE_ReadUnpack(&ModebusHandle1, &FrameInfo1);
						//????
						//usb_printf("??????(%d)?%d??????,?????%d?\r\n", FrameInfo1.SlaveAddr,  FrameInfo1.StartReg, FrameInfo1.RegNum);
						//??
						
						
						MODEBUS_SLAVE_ReturnReadReg(&ModebusHandle1, FrameInfo1.fun, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, FrameInfo1.RegNum, rtu_buff);
						
//						else {
//						
//						 MODEBUS_HOST_ReadMultReg(&ModebusHandle2, 3 , 1, FrameInfo1.StartReg,FrameInfo1.RegNum,RegBuff);
//						 MODEBUS_SLAVE_ReturnReadReg(&ModebusHandle1, FrameInfo1.fun, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, FrameInfo1.RegNum, RegBuff);	
//						}
						
						}break;
					case MRTU_FUN_WRITE			:					//6
					{
						//??
						MODEBUS_SLAVE_WriteUnpack(&ModebusHandle1, &FrameInfo1, &data);
						//????
						//usb_printf("?????(%d)????%d??:0x%02X\r\n", FrameInfo1.SlaveAddr,  FrameInfo1.StartReg, data);
						//??
						//rtu_buff[FrameInfo1.StartReg] = data;
						
						calibration_i =1;
						MODEBUS_SLAVE_ReturnWriteHoldReg(&ModebusHandle1, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, data);
					}break;
					case MRTU_FUN_MWRITE		:					//10
					{
						//??
						MODEBUS_SLAVE_WriteMultUnpack(&ModebusHandle1, &FrameInfo1, RegBuff);
						//????
//						usb_printf("?????(%d),?%d??????,?%d?,???:", FrameInfo1.SlaveAddr,  FrameInfo1.StartReg, FrameInfo1.RegNum);
//						for(i = 0;i < FrameInfo1.RegNum;i ++)
//						{
//							usb_printf("0x%04X ", RegBuff[i]);	//????
//						}
//						usb_printf("\r\n");
						//??
						if(FrameInfo1.StartReg<0x800){
							memcpy(rtu_buff+ FrameInfo1.StartReg,RegBuff,FrameInfo1.RegNum*2);
						//memcpy(rtu_buff,RegBuff,2);
							MODEBUS_SLAVE_ReturnWriteMultHoldReg(&ModebusHandle1, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, FrameInfo1.RegNum);
						}
						else{
							   
							if(RegBuff[0] ==0xaaaa)
							{
							v_k[(RegBuff[1]-1)]=v_k[(RegBuff[1]-1)]* (((float)RegBuff[2] /100.00)/dc_v[(RegBuff[1]-1)]);			
						//	v_k[1]=v_k[1]* (((float)RegBuff[3] /100.00)/dc_v[1]);					
						//	v_k[2]=v_k[2]* (((float)RegBuff[4] /100.00)/dc_v[12]);									
							writeFlashTest();	
							}
							
							if(RegBuff[0] ==0xbbbb)
							{
						   if(dc_i[(RegBuff[1]-1)] > 0){
								 i_k_a[(RegBuff[1]-1)]=i_k_a[(RegBuff[1]-1)]*(((float)RegBuff[2] /100.00)/dc_i[(RegBuff[1]-1)]);		
						  //  i_k_a[1]=i_k_a[1]*(((float)RegBuff[3] /100.00)/dc_i[1]);	
						  //  i_k_a[2]=i_k_a[2]*(((float)RegBuff[4] /100.00)/dc_i[12]);	
								 }	
               if(dc_i[(RegBuff[1]-1)] < 0){
								 i_k_a[(RegBuff[1]-1)]=i_k_a[(RegBuff[1]-1)]*(((float)RegBuff[2] /100.00)/(-dc_i[(RegBuff[1]-1)]));		
						  //  i_k_a[1]=i_k_a[1]*(((float)RegBuff[3] /100.00)/dc_i[1]);	
						  //  i_k_a[2]=i_k_a[2]*(((float)RegBuff[4] /100.00)/dc_i[12]);	
								 }									 
							writeFlashTest();	
							}
							
								MODEBUS_SLAVE_ReturnWriteMultHoldReg(&ModebusHandle1, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, FrameInfo1.RegNum);
							}
//						}
						
						}break;
					
					
					case MRTU_FUN_WRITE_ADD		:					//11
					{
						//??
						MODEBUS_SLAVE_WriteUnpack(&ModebusHandle1, &FrameInfo1, &data);
						
						//????
						//usb_printf("?????(%d)????%d??:0x%02X\r\n", FrameInfo1.SlaveAddr,  FrameInfo1.StartReg, data);
				       
						//??
						MODEBUS_SLAVE_ReturnWrite_add(&ModebusHandle1, FrameInfo1.SlaveAddr, FrameInfo1.StartReg, data); //
					}break;
					default:break;
				}
				
			}
			//MODEBUS_EnableRx(ModebusHandle1.UartCh);	//????
			 LL_USART_EnableIT_RXNE(USART1);
		}
	
		//OSTimeDlyHMSM(0,0,0,200);
		osDelay(100);
	}	
}
  /* USER CODE END Startmodbus_rtu */
}

/* USER CODE BEGIN Header_Startled_Task */
/**
* @brief Function implementing the myled_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Startled_Task */
void Startled_Task(void *argument)
{
  /* USER CODE BEGIN Startled_Task */
  /* Infinite loop */
	/*UDP自动上传参数*/
	int aaa = 1;
	int charge_led_step = 0;
	int charge_led_dir = 1; // 1表示递增，0表示递减
  for(;;)
  {
		 
		 if(udp_status == 1)  {
			 
     MODEBUS_SLAVE_ReturnReadReg(&ModebusHandle1, 03, modbue_SlaveAddr, 128, 98, rtu_buff);
			 
		 }
	if(BAT_EN == 1)	{  // 电池在线
		// 检查是否在充电状态（ch_stade1 = 1表示充电中）
		if(ch_stade1 == 1) {
			// 充电时实现追逐闪烁效果
			// 追逐效果：20% -> 40% -> 60% -> 80% -> 20%...
			charge_led_step++;
			if(charge_led_step >= 5) {
				charge_led_step = 0;
			}
			
			// 先关闭所有LED
			
			
			// 根据当前步数设置追逐效果
			switch(charge_led_step) {
			case 0:	
				LL_GPIO_SetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
			LL_GPIO_SetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
			LL_GPIO_SetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
			LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			break;
				case 1:
					// 第一步：只亮20%LED
					if(SOC >= 5) {
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					}
					break;
				case 2:
					// 第二步：只亮40%LED
					if(SOC >= 25) {
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 5) {
						// 如果SOC低于25%，则继续显示20%LED
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					}
					break;
				case 3:
					// 第三步：只亮60%LED
					if(SOC >= 50) {
						LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 25) {
						// 如果SOC低于50%，则显示40%LED
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 5) {
						// 如果SOC低于25%，则显示20%LED
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					}
					break;
				case 4:
					// 第四步：只亮80%LED
					if(SOC >= 75) {
						LL_GPIO_ResetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
						LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 50) {
						// 如果SOC低于75%，则显示60%LED
						LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 25) {
						// 如果SOC低于50%，则显示40%LED
						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					} else if(SOC >= 5) {
						// 如果SOC低于25%，则显示20%LED
						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
					}
					break;
//				case 4:
//					// 第五步：根据SOC显示最高级别的LED
//					if(SOC >= 75) {
//						LL_GPIO_ResetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
//					} else if(SOC >= 50) {
//						LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
//					} else if(SOC >= 25) {
//						LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
//					} else if(SOC >= 5) {
//						LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
//					}
//					break;
			}
			osDelay(500); // 充电时追逐闪烁速度
		} else {
			// 停止充电或充满后，按当前SOC稳定显示
			if(SOC > 85){
				LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
				LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
				LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
				LL_GPIO_ResetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			}
			else if(SOC <= 85 && SOC > 50){
				LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
				LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
				LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
				LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			}
			else if(SOC <= 50 && SOC > 25){
				LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
				LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
				LL_GPIO_SetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
				LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			}
			else if(SOC <= 25 && SOC > 5){
				LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
				LL_GPIO_SetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
				LL_GPIO_SetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
				LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			}
			else if(SOC <= 5){
				LL_GPIO_SetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
				LL_GPIO_SetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
				LL_GPIO_SetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
				LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			}
			osDelay(1000); // 稳定显示时延迟较长
		}
	} else {
		// 电池不在线时，指示灯快速全亮全灭闪亮
		if(aaa == 1){
    LL_GPIO_SetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
		LL_GPIO_SetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
		LL_GPIO_SetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
		LL_GPIO_SetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
		aaa = 0;
		}else{
			LL_GPIO_ResetOutputPin(POW20_LED_GPIO_Port, POW20_LED_Pin);
			LL_GPIO_ResetOutputPin(POW40_LED_GPIO_Port, POW40_LED_Pin);
			LL_GPIO_ResetOutputPin(POW60_LED_GPIO_Port, POW60_LED_Pin);
			LL_GPIO_ResetOutputPin(POW80_LED_GPIO_Port, POW80_LED_Pin);
			aaa = 1;
		}
		osDelay(200); // 快速闪烁
	}
  }
  /* USER CODE END Startled_Task */
}

/* USER CODE BEGIN Header_Startbms_Task */
/**
* @brief Function implementing the mybms_task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Startbms_Task */
void Startbms_Task(void *argument)
{
  /* USER CODE BEGIN Startbms_Task */
  /* Infinite loop */
	/*���������·*/
	
	float temp_a;
	uint16_t bat_disch_c = 0;
	osDelay(5000);
	rtu_buff[130] = SOC;
	rtu_buff[131] = SOH;
	rtu_buff[132] = battery_capacity_rate * SOC / 100;
	rtu_buff[133] = battery_capacity;
	rtu_buff[134] = battery_capacity_rate;
	rtu_buff[135] = battery_cyc;	
	battery_capacity = rtu_buff[132] ;
  for(;;)
  {			
			/*********�����������*******/
			
			if(battery_i <= -0.05 ){									
			battery_capacity = battery_capacity + ((-battery_i * 1000 ) / 3600);				
				if(battery_capacity >= battery_capacity_rate ){
					battery_capacity = battery_capacity_rate;
					bat_charge_indicator = 1;						
				}
				
        if(battery_v >= rtu_buff[137] * 3.65){
			battery_capacity = battery_capacity_rate;
			bat_charge_indicator = 1;
			battery_full = 1;  // 标记电池已充满
			ch_stade = 0;  // 关闭充电
			}											
			}
			
			/*********�ŵ���������*******/
			
			if(battery_i >= 0.05 ){
			battery_capacity = battery_capacity - ((battery_i * 1000 ) / 3600);
				if(battery_capacity <= 0 ){
					battery_capacity = 0;	
				}
        if(battery_v<= rtu_buff[137] * 2.7){
				//battery_capacity_soc = 0;	
				bat_disch_c++;
						if(bat_disch_c >= 4){
						   if(battery_v<= rtu_buff[137] * 2.7){
						      battery_capacity = 0;
							  bat_discharge_indication = 1;	
						                     }else{bat_disch_c = 0;}						
						                        }
				                  }
				else{bat_disch_c =0 ;}
								
      if(battery_capacity <= battery_capacity_rate * 0.1){
       bat_discharge_indication = 1;
		}
		
		// 当电池自放电到90%以下且之前已经充满过时，重新开启充电
		if(battery_full && battery_capacity <= battery_capacity_rate * 0.9 && POWER_STATE == 1){
			ch_stade = 1;  // 重新开启充电
			battery_full = 0;  // 重置电池充满标志
		}				
			}	
    if(battery_v >= rtu_buff[137] * 3.65){
				battery_capacity = battery_capacity_rate;	
				bat_charge_indicator = 1;
				}		
										
    if(battery_v<= rtu_buff[137] * 2.7){
				//battery_capacity_soc = 0;	
				bat_disch_c++;
						if(bat_disch_c >= 4){
						   if(battery_v <= rtu_buff[137] * 2.7){
								 bat_disch_c = 0;
						         battery_capacity = 0;	
						                     }else{bat_disch_c = 0;}						
						                        }
				                  }
		SOC = battery_capacity * 100 / battery_capacity_rate;	
		rtu_buff[130] = SOC;
    osDelay(1000);
  }
  /* USER CODE END Startbms_Task */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void Start_TC_Task(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	/*��ѹ���������¶Ȳɼ��Լ�У׼����Դ״̬�ɼ�*/
	uint32_t  v,i;
	uint16_t v_max,i_max,i_min;
	uint16_t v_min;
	u16 data;
	int16_t RegBuff[30];
//	u8 i;
	u8 cont;
	u32 cnt1 = 0,cnt2 = 0;
	u8 Fun;
	u16  pRegData;
	u8 ii1 = 0;
	u8 ii2 = 0;
	u8 ii3 = 0; 
	uint16_t  ctrl = 0;
	uint16_t temp;
	uint8_t dianliu;
	uint16_t sum =0;
  uint8_t cheaksum,a;
	float reg;
	float temp_float;
  float temp_a;
	float bus_v, current, shunt_v;
	rtu_buff[199] = 0xD2;
  uint8_t res;
	uint8_t out_sum_temp = 0;
	 LL_USART_EnableIT_RXNE(USART2);	 
	 LL_USART_EnableIT_IDLE(USART2);
   //MODEBUS_host_Init(&ModebusHandle2, 01, 115200, ModebusRxBuff_M, ModebusTxBuff_M, 128-1, 200);	
	 
	 LL_USART_EnableDMAReq_TX(USART1);
	 LL_USART_EnableIT_RXNE(USART1);
	 LL_USART_EnableIT_IDLE(USART1);
	 LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_4, (uint32_t)ModebusTxBuff);
     LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_4, (uint32_t)(&USART1->DR));     	
	 LL_DMA_EnableIT_TC(DMA1,LL_DMA_CHANNEL_4);
     calibration_i =0;
	 LL_mDelay(200);
	 int bbb = 0;
   /* ��ʼ��INA266�豸 */
    if(INA226_Init(&dev1) != INA226_OK) {
//			if(INA226_Init(&dev1) != INA226_OK){
       // HandleError(INA226_ERR_INIT);
        OUT1_266 = 0;
			}
    else{OUT1_266 = 1;}			
	 LL_mDelay(200);
		
    if(INA226_Init(&dev2) != INA226_OK) {
//      if(INA226_Init(&dev2) != INA226_OK){
       // HandleError(INA226_ERR_INIT);
        OUT2_266 = 0;
			}
    else{OUT2_266 = 1;}
		
	  if(INA226_Init(&dev3) != INA226_OK) {
      if(INA226_Init(&dev3) != INA226_OK){
       // HandleError(INA226_ERR_INIT);
       BAT_266 = 0;
			}
    }else{BAT_266 = 1;}
	 	
  /* Infinite loop */
  for(;;)
  { 
		
		
		if(calibration_i ==1 ){
		
		calibration_i =0;
			
//		i_k[5] = (float)(((aADCxConvertedData[11])*3300.0/4096.0/1000)*1.515);
//		i_k[4] = (float)(((aADCxConvertedData[1])*3300.0/4096.0/1000)*1.515);
//		i_k[3] = (float)(((aADCxConvertedData[3])*3300.0/4096.0/1000)*1.515);
		i_k[0] = (float)(((aADCxConvertedData[0])*3300.0/4096.0/1000)*2.87);
		i_k[1] = (float)(((aADCxConvertedData[2])*3300.0/4096.0/1000)*2.87);
		i_k[2] = (float)((aADCxConvertedData[5])*3300.0/4096.0/1000);	
	writeFlashTest();			

		}
		if(calibration_i ==2 ){
		
		calibration_i =0;
//		i_k[4] = (float)(((aADCxConvertedData[1])*3300.0/4096.0/1000)*1.515);
//		i_k[3] = (float)(((aADCxConvertedData[3])*3300.0/4096.0/1000)*1.515);
//		i_k[2] = (float)(((aADCxConvertedData[5])*3300.0/4096.0/1000)*1.515);
//		i_k[1] = (float)(((aADCxConvertedData[7])*3300.0/4096.0/1000)*1.515);
//		i_k[0] = (float)(((aADCxConvertedData[9])*3300.0/4096.0/1000)*1.515);			
			
		writeFlashTest();
		//tx_buff_uart(USART1,tx_uart_buff,8);
		
		}
	
	
		 

        //////////////////////////		
			
			
			/*�����¶�*/
		 for(tem=0;tem<340;tem++)
    {
		 if( t_adc[tem]>aADCxConvertedData[1])
		 break;
		}
	tem = (tem-40)*10;
   	rtu_buff[138] = tem;
	// printf("dianliu = %d \n",(tem);			
	device_tem = (float )tem/10.00;
		
		/*����¶�*/
		
//		for(tem=0;tem<340;tem++)
//    {
//		 if( t_adc[tem]>aADCxConvertedData[0])
//		 break;
//		}
//	tem = (tem-40)*10;
//   	rtu_buff[187] = tem;
//		rtu_buff[198] = tem;
//	// printf("dianliu = %d \n",(tem);			
//	tempre = (float )tem/10.00;
		
	
		
	  	/*��س�ŵ�״̬*/
		
		 /*�����ѹ����������ص�ѹ����������*/
		

        /* ��ȡ�����豸1-���1·���� */
	
        res = INA226_ReadAll(&dev1, &bus_v, &current, &shunt_v);
        if(res == INA226_OK) {
           // printf("Dev1: %.2fV, %.3fA, Shunt: %.2fmV\n",
                //  bus_v, current, shunt_v*1000);
					dc_v[0] = bus_v* v_k[0];
					dc_i[0] = current * i_k_a[0]/1.05;
        } else {
					res = INA226_ReadAll(&dev1, &bus_v, &current, &shunt_v);  //����
        if(res == INA226_OK) {
           // printf("Dev1: %.2fV, %.3fA, Shunt: %.2fmV\n",
                //  bus_v, current, shunt_v*1000);
					dc_v[0] = bus_v* v_k[0];
					dc_i[0] = current * i_k_a[0]/1.05;
				}else{
					dc_v[0] = 0;
					dc_i[0] = 0;
				}            
        }
        rtu_buff[157] = (uint16_t)(dc_v[0]*100);
				rtu_buff[158] = (uint16_t)(dc_i[0]*100);
				
        /* ��ȡ�����豸2-���2·���� */
				
        res = INA226_ReadAll(&dev2, &bus_v, &current, &shunt_v);
        if(res == INA226_OK) {
           // printf("Dev2: %.2fV, %.3fA, Shunt: %.2fmV\n",
              //    bus_v, current, shunt_v*1000);
					dc_v[1] = bus_v * v_k[1];
					dc_i[1] = current* i_k_a[1]/1.05;
        } else {
					res = INA226_ReadAll(&dev2, &bus_v, &current, &shunt_v);  //����
        if(res == INA226_OK) {
           // printf("Dev1: %.2fV, %.3fA, Shunt: %.2fmV\n",
                //  bus_v, current, shunt_v*1000);
					dc_v[1] = bus_v* v_k[0];
					dc_i[1] = current * i_k_a[1]/1.05;
				}else{
					dc_v[1] = 0;
					dc_i[1] = 0;
				     }       
           
        }
				rtu_buff[159] = (uint16_t)(dc_v[1]*100);
				rtu_buff[160] = (uint16_t)(dc_i[1]*100);
				
				 /* ��ȡ�����豸3����ز��� */
				
        res = INA226_ReadAll(&dev3, &bus_v, &current, &shunt_v);
        if(res == INA226_OK) {
           // printf("Dev2: %.2fV, %.3fA, Shunt: %.2fmV\n",
              //    bus_v, current, shunt_v*1000);
					dc_v[12] = bus_v* v_k[12];
					dc_i[12] = current* i_k_a[12]/1.05;
        } else {
					res = INA226_ReadAll(&dev3, &bus_v, &current, &shunt_v);  //����
        if(res == INA226_OK) {
           // printf("Dev1: %.2fV, %.3fA, Shunt: %.2fmV\n",
                //  bus_v, current, shunt_v*1000);
					dc_v[12] = bus_v* v_k[12];
					dc_i[12] = current * i_k_a[12]/1.05;
				}else{
					dc_v[12] = 0;
					dc_i[12] = 0;
				     }                  
        }
 osDelay(100);

		 ///////////////////////////////////

				
				battery_v = dc_v[12];
				battery_i = dc_i[12] ;
				rtu_buff[128] = (int16_t)(battery_i*100);
				rtu_buff[129] = (uint16_t)(dc_v[12]*100);
		 
		if(battery_i < -0.1){                                                                                                                               
		num_pic_bat_status = 3;
		
		}
		if(battery_i > 0.1){
		num_pic_bat_status = 2;
		}
		if((battery_i >= -0.1) & (battery_i <= 0.1)){
		num_pic_bat_status = 4;
		}
		
		 if(SOC<=20)
		 {
		 num_pic_battery = 5;
			 }else if (SOC<= 40){
			 num_pic_battery = 4;
			 }else if (SOC<= 60){

			 num_pic_battery = 3;
			 }else if (SOC<= 80){
			 
			 num_pic_battery = 2;
			 }else {
			 num_pic_battery = 1;
			 }
		
		///////////////////////////
		
		/*���硢���������״̬*/
			rtu_buff[137] = 6; //����鴮��
		    rtu_buff[151] = modbue_SlaveAddr;  //485��ַ
			rtu_buff[152] = modbue_Baud;  //485������ 
			rtu_buff[156] = 2;  //���·�� 			
			 
			 
			 
		/*�澯���*/	 

		ctrl = rtu_buff[136];//AC����澯
	if(!LL_GPIO_IsInputPinSet(PG_GPIO_Port,PG_Pin)){
		rtu_buff[136] = (ctrl & 0XFFFE);
      PREV_POWER_STATE = POWER_STATE;  // 保存上一次状态
		POWER_STATE = 1;
		// 检测电源恢复（从0变为1）
		if(PREV_POWER_STATE == 0 && POWER_STATE == 1){
			ch_stade = 1;  // 强制开启充电
			battery_full = 0;  // 重置电池充满标志，确保优先补电
		}
		}
		else {
rtu_buff[136]=(ctrl | 0X0001);
      PREV_POWER_STATE = POWER_STATE;  // 保存上一次状态
		POWER_STATE = 0;
		}
		ctrl = rtu_buff[136];//��ص����澯
	if(battery_capacity <= 20){
		rtu_buff[136] = (ctrl | 0X0002);
	}else{
	rtu_buff[136] = (ctrl & 0XFFFD);
	}
	ctrl = rtu_buff[136];//��س��¸澯
	if(device_tem >= 50){
		rtu_buff[136] = (ctrl | 0X0004);
	}else{
	rtu_buff[136] = (ctrl & 0XFFFB);
	}
	ctrl = rtu_buff[136];//��ص��¸澯
	if(device_tem <= -20){
		rtu_buff[136] = (ctrl | 0X0008);
	}else{
	rtu_buff[136] = (ctrl & 0XFFF7);
	}
	ctrl = rtu_buff[136];//���1·�澯
	if(dc_v[0] <= 10){
		rtu_buff[136] = (ctrl | 0X0010);
	}else{
	rtu_buff[136] = (ctrl & 0XFFEF);
	}
	ctrl = rtu_buff[136];//���2·�澯
	if(dc_v[1] <= 10){
		rtu_buff[136] = (ctrl | 0X0020);
	}else{
	rtu_buff[136] = (ctrl & 0XFFDF);
	}	
		
	if(POWER_STATE == 1){
		if(ctrl_1 == 1){
	if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){	
      osDelay(200);	
       if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){		
		BAT_EN = 0;
		ctrl_1 = 0;
		}
	}
                       }
		if(ctrl_1 == 0) {
		if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){
				osDelay(200);	
		if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){
		BAT_EN = 1;
		ctrl_1 = 1;
				}
		}
		}
	}
		else{ 
		if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){	
        osDelay(200);	
        if(!LL_GPIO_IsInputPinSet(CTRL_BAT_GPIO_Port,CTRL_BAT_Pin)){		
		BAT_EN = 0;
		}
	    }
			}				
	                                /*AC����ָʾ*/
					if(POWER_STATE == 1)
					{
					LL_GPIO_ResetOutputPin(POW_LED_GPIO_Port,POW_LED_Pin);
					}
					else{
						if(bbb == 0){
					LL_GPIO_SetOutputPin(POW_LED_GPIO_Port,POW_LED_Pin);
					bbb = 1;
						}else{
					LL_GPIO_ResetOutputPin(POW_LED_GPIO_Port,POW_LED_Pin);
					bbb = 0;
						}
					}
					
					/*���ָʾ&�������ָʾ*/
					
					if(BAT_EN == 1 ){
					
					if(battery_i <= -0.1){
						
					if((rtu_buff[3]&0X0004) && ch_stade && (!LL_GPIO_IsInputPinSet(PG_GPIO_Port,PG_Pin))){
			        ch_stade1  = 1;
			        }else{
					ch_stade1  = 0;
			      }
					}else{
					ch_stade1  = 0;
			      }
												  	
				}
osDelay(1000);
				
	}	
	
  /* USER CODE END StartDefaultTask */
}

void Start_cmd_Task(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
	 /*����ָ����Ӧ*/
	
 uint8_t tmp ,crc;
 uint16_t cmd_crc;
uint16_t ctrl_temp;
 uint8_t buff[10];
	
 static uint8_t rx_state_pc=0;
 static uint8_t rx_cont=0;
	
	uint8_t cChar;	
	vSemaphoreCreateBinary(xSemaphoreRecf_pc_uart1);	
	xQueueRx_pc_uart1 = xQueueCreate(50, sizeof(uint8_t));
	cmd_crc =0;
	
	LL_USART_EnableIT_RXNE(USART1);
	osDelay(2000);
	
  //usb_printf(" cmd_Task task is ok \n");

  /* Infinite loop */
  for(;;)
  {

		
		      /*********************************************************/
					/**********************03�Ĵ���***************************/
					/**************************  4  **  3  **  2  ** 1 *** 0 */
					/**************************����2***����1***���***���***AC*/
		      /*********************************************************/				
	
		      if(rtu_buff[3]&0X0001){
						
						LL_GPIO_ResetOutputPin(CNT1_GPIO_Port,CNT1_Pin); // ����1·����
					}
					else {
					
			     LL_GPIO_SetOutputPin(CNT1_GPIO_Port,CNT1_Pin);
					}	
		
					if(rtu_buff[3]&0X0002){
						
						LL_GPIO_ResetOutputPin(CNT2_GPIO_Port,CNT2_Pin); // ����2·����
					}
					else {
					
			     LL_GPIO_SetOutputPin(CNT2_GPIO_Port,CNT2_Pin);
					}	
					if(rtu_buff[3]&0x1000){//7
    			   LL_GPIO_ResetOutputPin(EN_AC_GPIO_Port,EN_AC_Pin);  //AC����
					}
		else {
					LL_GPIO_SetOutputPin(EN_AC_GPIO_Port,EN_AC_Pin);
				
					}
		
			if(((rtu_buff[3]&0x2000)&& BAT_EN ) ){//8
					
          	LL_GPIO_ResetOutputPin(EN_BAT_GPIO_Port,EN_BAT_Pin);  //��ؿ���
				
					}
					else {
					 
		              writeFlashTest();
		        osDelay(100);     
					  LL_GPIO_SetOutputPin(EN_BAT_GPIO_Port,EN_BAT_Pin);  
					}					
					
					if((rtu_buff[3]&0x4000) && ch_stade && BAT_STATE1){    //9   ////6900���оƬ
						
						LL_GPIO_ResetOutputPin(EN_CH_GPIO_Port,EN_CH_Pin);						// ������
					}
					else {
					
			            LL_GPIO_SetOutputPin(EN_CH_GPIO_Port,EN_CH_Pin);
					}
									
					rtu_buff[155]	= rtu_buff[3];
					
					
							
				if(bat_discharge_indication && bat_charge_indicator)//ѭ��������1
			{
				battery_cyc++;
				writeFlashTest();
			}				      
           if(rtu_buff[151] != modbue_SlaveAddr){		   
		   modbue_SlaveAddr = rtu_buff[151];
		   writeFlashTest();
		   }								   
		   if(rtu_buff[154] != udp_status){		   
		   udp_status = rtu_buff[154];
		   writeFlashTest();
		   }
			 if(rtu_buff[152] != modbue_Baud){		   
		   modbue_Baud = rtu_buff[152];
		     LL_USART_Disable(USART1);
             LL_USART_InitTypeDef USART_InitStruct = {0};
             LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; 
             USART_InitStruct.BaudRate = modbue_Baud*100;
             USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
             USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
             USART_InitStruct.Parity = LL_USART_PARITY_NONE;
             USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
             USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
             USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
             LL_USART_Init(USART1, &USART_InitStruct);
             LL_USART_ConfigAsyncMode(USART1);
             LL_USART_Enable(USART1);
             LL_USART_EnableIT_RXNE(USART1);
	         LL_USART_EnableIT_IDLE(USART1);
			 MODEBUS_slave_Init(&ModebusHandle1, 01, modbue_Baud*100, ModebusRxBuff, ModebusTxBuff, 128-1, 200);
		   writeFlashTest();
		   }		   		   			 
			if(rtu_buff[135] != battery_cyc){		   
		   battery_cyc = rtu_buff[135];
		   writeFlashTest();
		   }
				
			 // 根据电池循环次数更新SOH
			 UpdateBatteryCapacity();
			 int new_SOH = CalculateSOH();
			 
			 // 如果计算得到的SOH与当前值不同，更新并保存到Flash
			 if(new_SOH != SOH){		                         
		   SOH = new_SOH;
			 rtu_buff[131] =  SOH;
		   writeFlashTest();
		   }
		   
		   // 同时也可以从外部输入更新SOH（如调试或校准用）
		   if(rtu_buff[131] != SOH){  // 如果rtu_buff[131]不为0，表示外部有更新
			   SOH = rtu_buff[131];
			   writeFlashTest();
		   }
    osDelay(200);
		 }  
  /* USER CODE END StartDefaultTask */
}





/* USER CODE END Application */

